/**
 *  agents
 *  Author: tom thanhkm
 *  Description: Multi agents model of Daisy world
 */

model ModelAgents

/* Insert your model definition here */
global {
	float MIN_SIZE <- 2.0;
	float MAX_SIZE <- 3.0;
	float GROW_RATE <- 0.003265;
	float DEATH_RATE <- 0.3;
	float luminosity <- 0.6;//before 1.2
	float SOLAR_CONSTANT <- 864.65 ; //864.65 W m-2 ou 1368.0
	float SIGMA <- 5.67E-8; // the Stefan-Boltzmann constant 5.67x10^-8 Wm^-2K^-2
	float PI <- 3.14;
	float ALBEDO_BLACK <- 0.25;
	float ALBEDO_WHITE <- 0.75;
	float ALBEDO_GROUND <- 0.5;
	float TEMPERATURE <- 295.5; // optimal temperature for daisy growth
	float TOB <- 290.5;	// optimal temperature for daisy black growth
	float TOW <- 300.5;	// optimal temperature for daisy white growth

	float temperature_init <- 253.0; // optimal temperature for daisy growth
	float C <- 2500.0; //Heat capacity 2500 Wm^-2K^-2
	float DT <- 500.0; //Diffusion constant 500 Wm^-2K^-2
	float D <- DT/C;
	int WORLD_SIZE <- 150;
	int NB_CELL <- 150;
	float planetTemperature <- temperature_init;
	float planetTemperatureWithoutDaisy <- temperature_init;
	float coverByBlack <- 0.0;
	float coverByWhite <- 0.0;	
	init {		
		create seed_black number: NB_CELL*NB_CELL/10 {
			longvity <- gauss(20, 500);
		}
		create seed_white number: NB_CELL*NB_CELL/10 {
			//size <- 1.0;
			longvity <- gauss(20, 500);
		}
		create foo number: 1 {
			//size <- 1.0;
		}
	}
//	reflex stop_simulation when: luminosity > 1.77 {
//		do halt ;
//	}
}

entities {
	species daisy{
		
	}
	//-----------------DAISY BLACK-------------------------------------------------------
	//-----------------------------------------------------------------------------------
	species daisy_black parent: daisy{
		float size <- rnd(MAX_SIZE - MIN_SIZE) + MIN_SIZE;
		geometry shape <- circle(size);
		rgb color <- rgb("black") ;
		float albedo <- ALBEDO_BLACK;
		const IMAGE_BLACK type: file <- file("../images/margueriteNoire33.png");	
		
//		list<cell> list_cells <- agents_overlapping ( self ) of_species cell; // listes de cells que l'agent appartient
		
		init {
			shape <- circle(size);
			
		}
		
		//reproduction of daisy
		reflex reproduction{
			point loc <- any_location_in(location enlarged_by(2*MAX_SIZE));
			if(loc.x >= 0 and loc.y >=0 
				and loc.x < WORLD_SIZE and loc.y < WORLD_SIZE){
				create seed_black number: 1 {
					set location <- loc;
					longvity <- gauss(2.0, 50.0);
				}							
			}
		}
		
		//elle va mourrir apres duree_vivre
		reflex vivre {
//			set color <- rgb(20 + rnd(155),20 + rnd(155),20 + rnd(155));
			if (flip(DEATH_RATE)) {
				do action: die ;
			}
		}

		//create a daisy
		action create_daisy {
			arg position type: point;
			arg taille type: float;
			create daisy_black number : 1 {
				set location <- position ;
				set size <- taille;
			}
		}
		
		aspect base {
			draw shape: circle(size) color: color ;
		}
		aspect image{
			draw IMAGE_BLACK size: 2* size;
		}
	}
	
	//-----------------DAISY WHITE-------------------------------------------------------
	//-----------------------------------------------------------------------------------
	species daisy_white parent: daisy{
		float size <- rnd(MAX_SIZE - MIN_SIZE) + MIN_SIZE;
		geometry shape <- circle(size);
		rgb color <- rgb("white") ;
		float albedo <- ALBEDO_WHITE;
		const IMAGE_WHITE type: file <- file("../images/margueriteBlanche33.png");
		
//		list<cell> list_cells <- agents_overlapping ( self ) of_species cell; // listes de cells que l'agent appartient
		
		init {
			shape <- circle(size);			
		}
		
		//reproduction of daisy
		reflex reproduction{
			point loc <- any_location_in(location enlarged_by(2*MAX_SIZE));
			if(loc.x >= 0 and loc.y >=0 
				and loc.x < WORLD_SIZE and loc.y < WORLD_SIZE){
				create seed_white number: 1 {
					set location <- loc;
					longvity <- gauss(2.0, 50.0);
				}							
			}
		}
		
		//elle va mourrir apres duree_vivre
		reflex vivre {
//			set color <- rgb(20 + rnd(155),20 + rnd(155),20 + rnd(155));
			if (flip(DEATH_RATE)) {
				do action: die ;
			}
		}

		//create a daisy
		action create_daisy {
			arg position type: point;
			arg taille type: float;
			create daisy_white number : 1 {
				set location <- position ;
				set size <- taille;
			}
		}
		
		aspect base {
			draw shape: circle(size) color: color ;
		}
		aspect image{
			draw IMAGE_WHITE size: 2* size;
		}		
	}

	species seed{
		int longvity;
		action grow{
			
		}
	}
	
	species seed_black parent: seed {
		float size <- 0.01;
		geometry shape <- circle(size);
		rgb color <- rgb("blue");
		int nb_time <- 0;
		cell my_cell <- first(cell overlapping location);
		init{
		}
		
		action grow{						
			size <- rnd(MAX_SIZE - MIN_SIZE) + MIN_SIZE;
			shape <- circle(size);
			int a <- length(daisy_black overlapping self as list)
			+ length(daisy_white overlapping self as list);			
			if (flip(my_cell.growRateBlack) and a <= 0 and nb_time > 0 and location.x >= 0 and location.y >=0 
				and location.x < WORLD_SIZE and location.y < WORLD_SIZE){
				create daisy_black number: 1{
					set location <- myself.location;
					set size <- myself.size;
				}
				do action: die;
			}else if(nb_time > longvity){
				do action: die;				
			}
			nb_time <- nb_time + 1;			
			size <- 0.01;
			shape <- circle(size);
		}
		aspect base {
			draw shape: circle(size) color: color ;
		}
	}			

	species seed_white parent: seed {
		float size <- 0.01;
		geometry shape <- circle(size);
		rgb color <- rgb("cyan");
		int nb_time <- 0;
		cell my_cell <- first(cell overlapping location);
		init{
		}
		
		action grow{
			size <- rnd(MAX_SIZE - MIN_SIZE) + MIN_SIZE;
			shape <- circle(size);
			int a <- length(daisy_black overlapping self as list)
					+ length(daisy_white overlapping self as list);							
			if (flip(my_cell.growRateWhite) and a <= 0 and nb_time > 0 and location.x >= 0 and location.y >=0 
				and location.x < WORLD_SIZE and location.y < WORLD_SIZE){
				create daisy_white number: 1{				
					set location <- myself.location;
					set size <- myself.size;
				}
				do action: die;
			}else if(nb_time > longvity){
				do action: die;	
			}
			nb_time <- nb_time + 1;
			size <- 0.01;
			shape <- circle(size);
		}
		aspect base {
			draw shape: circle(size) color: color ;
		}
	}
	
    //-----------------CELL--------------------------------------------------------------
	//-----------------------------------------------------------------------------------
	grid cell width: NB_CELL height: NB_CELL neighbours: 4 {		
		rgb color <- rgb(50+300*((temperature_init - 273)/ (320-273)),0,0);
//		float size <- CELL_SIZE;
		//geometry shape;// <- square (size); 
		geometry ground; 
		float temperature <- temperature_init;
		float temperatureNew <- temperature;
		float temperatureWithoutDaisy <- temperature_init;
		float temperatureWithoutDaisyNew <- temperature;
		float areaBlack;
		float areaWhite;
		float areaGround;
		
		float fractionAreaBlack;
		float fractionAreaWhite;
		float fractionAreaGround;
		float growRateBlack <- 0.0;
		float growRateWhite <- 0.0;
		float albedo;
		
		//le temps que les daisy vivent
		float temp_vivre <- 0.0 ;
		
		//nombre des daisy
		int nb_daisy_white <-0;
		int nb_daisy_black <-0;
		list<cell> neighbours  <- (self neighbours_at 1);
		int nb_count <- length(neighbours);		
		
		action calculTemperature {
			float X <- ( 1 - D ) * temperature;
			loop neighbour over: neighbours{				
				X <- X + D/nb_count * neighbour.temperature;
			}
			temperatureNew <- X + (SOLAR_CONSTANT*luminosity*(1 - albedo) - SIGMA*(X^4))/C + gauss(0, 1.0);
//write "albedo: " + albedo;
		 	color <- rgb(50+300*((temperature - 273)/ (320-273)),0,0);
		}

		action calculTemperatureWithoutDaisy {
			float X <- ( 1 - D ) * temperatureWithoutDaisy;
			loop neighbour over: neighbours{				
				X <- X + D/nb_count * neighbour.temperatureWithoutDaisy;
			}
			temperatureWithoutDaisyNew <- X + (SOLAR_CONSTANT*luminosity*(1 - ALBEDO_GROUND) - SIGMA*(X^4))/C + gauss(0, 1.0);
		}


		reflex calculGrowRate{
			growRateBlack <- 1 - GROW_RATE * (TOB - temperature) * (TOB - temperature);
			growRateWhite <- 1 - GROW_RATE * (TOW - temperature) * (TOW - temperature);
			if (growRateBlack < 0){
				growRateBlack <- 0.0;
			}
			if (growRateWhite < 0){
				growRateWhite <- 0.0;
			}
//write "Temp:" + temperature;
//write 'grow rate' + growRateBlack + "$"+ growRateWhite;
		}
		
		reflex updateAlbedo{
			int nb_black <- length(daisy_black overlapping self as list);
			int nb_white <- length(daisy_white overlapping self as list);
			if(nb_black > 0 and nb_white > 0){
				albedo <- (ALBEDO_BLACK + ALBEDO_WHITE) / 2;
			}else if (nb_black > 0){
				albedo <- ALBEDO_BLACK;
			}else if (nb_white > 0){
				albedo <- ALBEDO_WHITE;
			}else {
				albedo <- ALBEDO_GROUND;
			}
		}
		
		reflex raise{
			list<seed> my_seeds <- shuffle(seed_black overlapping self + seed_white overlapping self);
			if( growRateBlack > 0 or growRateWhite > 0 ){
				loop s over: my_seeds{
					ask s{
						do action: grow;				
					}				
				}			
			}
		}
	}			
}

species foo{
	reflex calculateWorldTemperature{				
		float temp <- 0.0;
		float tempWithoutDaisy <- 0.0;
		coverByBlack <- 0.0;
		coverByWhite <- 0.0;
		loop c over: (cell as list){
			temp <- temp + c.temperature;
			tempWithoutDaisy <- tempWithoutDaisy + c.temperatureWithoutDaisy;
			int nb_black <- length(daisy_black overlapping c as list);
			int nb_white <- length(daisy_white overlapping c as list);			
			if(nb_black > 0 and nb_white > 0){
				coverByBlack <- coverByBlack + 0.5;
				coverByWhite <- coverByWhite + 0.5;
			}else if (nb_black > 0){
				coverByBlack <- coverByBlack + 1.0;
			}else if (nb_white > 0){
				coverByWhite <- coverByWhite + 1.0;
			}
			
			//update teperature for this cell
			float X <- ( 1 - D ) * c.temperature;
			float Y <- ( 1 - D ) * c.temperatureWithoutDaisy;
			loop neighbour over: c.neighbours{				
				X <- X + D/c.nb_count * neighbour.temperature;
				Y <- Y + D/c.nb_count * neighbour.temperatureWithoutDaisy;
			}
			c.temperatureNew <- X + (SOLAR_CONSTANT*luminosity*(1 - c.albedo) - SIGMA*(X^4))/C + gauss(0, 1.0);
			c.temperatureWithoutDaisyNew <- Y + (SOLAR_CONSTANT*luminosity*(1 - ALBEDO_GROUND) - SIGMA*(Y^4))/C + gauss(0, 1.0);
		 	c.color <- rgb(50+300*((c.temperatureNew - 273)/ (320-273)),0,0);
			//update temperature for this cell in case there are no daisy									
		}
		//update temperature by new temperature
		loop c over: (cell as list){
			c.temperature <- c.temperatureNew;
			c.temperatureWithoutDaisy <- c.temperatureWithoutDaisyNew;
		}
		planetTemperature <- temp/NB_CELL/NB_CELL;
		planetTemperatureWithoutDaisy <- tempWithoutDaisy/NB_CELL/NB_CELL;
		luminosity <- luminosity + 0.0001;
	}
}
environment width: WORLD_SIZE height:WORLD_SIZE;

experiment daisy_world type: gui {
	parameter "Initial Temperature: " var: temperature_init category: "Planet" step: 1;
	parameter "luminosity: " var: luminosity category: "Planet" step: 0.01;
	parameter "Optimal temp for ds black: " var: TOB category: "Daisy" ;
	parameter "Optimal temp for ds white: " var: TOW category: "Daisy" ;
	parameter "Albedo of ds black: " var: ALBEDO_BLACK category: "Daisy" step: 0.01;
	parameter "Albedo of ds white: " var: ALBEDO_WHITE category: "Daisy" step: 0.01;
	parameter "Albedo of ground: " var: ALBEDO_GROUND category: "Daisy" ;
	
	output {
		monitor "seed black" value: length(seed_black as list);
		monitor "seed white" value: length(seed_white as list);
		monitor "daisy black" value: length(daisy_black as list);
		monitor "daisy white" value: length(daisy_white as list);
		monitor "Planet temperature" value: planetTemperature;
		monitor "Planet temp without ds" value: planetTemperatureWithoutDaisy;
		monitor "Area covered by ds black" value: coverByBlack/NB_CELL/NB_CELL;
		monitor "Area covered by ds white" value: coverByWhite/NB_CELL/NB_CELL;
		monitor "Luminosity" value: luminosity; 
		display main_display {
			species cell;
			species daisy_black aspect: image ;
			species daisy_white aspect: image ;
//			species seed_black aspect: base;
//			species seed_white aspect: base;
		}
		display Daisy_population refresh_every: 10 {
			chart "World temperature evolution" type: series background: rgb("white") size: {1, 0.4} position: {0, 0.05}{
				data "world temperature without daisy" value: planetTemperatureWithoutDaisy - 273 color: rgb("blue");
				data "world temperature with daisy" value: planetTemperature - 273 color: rgb("red");
				}
				
			chart "Daisy areas cover" type: series background: rgb("white") size: {1, 0.4} position: {0, 0.55}{
				data "areas of daisy black" value: coverByBlack/NB_CELL/NB_CELL color: rgb("black");
				data "areas of daisy white" value: coverByWhite/NB_CELL/NB_CELL color: rgb("blue");
				data "areas of ground" value: 1 - coverByBlack/NB_CELL/NB_CELL - coverByWhite/NB_CELL/NB_CELL color: rgb(204,74,0);
				
				}	
		}
	}
}
